package validator

import (
	"errors"
	"fitness/go-admin/internal/config"
	"fmt"
	"unicode"
)

// ValidatePassword 验证密码强度，根据配置文件中的安全策略进行验证
func ValidatePassword(password string) error {
	// 检查全局配置是否已初始化
	if config.GlobalConfig == nil {
		// 如果未初始化，使用默认策略
		if len(password) < 8 {
			return errors.New("密码长度至少需要8位")
		}

		if len(password) > 32 {
			return errors.New("密码长度不能超过32位")
		}

		var (
			hasUpper   = false
			hasLower   = false
			hasNumber  = false
			hasSpecial = false
		)

		// 检查每个字符
		for _, char := range password {
			switch {
			case unicode.IsUpper(char):
				hasUpper = true
			case unicode.IsLower(char):
				hasLower = true
			case unicode.IsNumber(char):
				hasNumber = true
			case unicode.IsPunct(char) || unicode.IsSymbol(char):
				hasSpecial = true
			}
		}

		if !hasUpper {
			return errors.New("密码必须包含至少一个大写字母")
		}
		if !hasLower {
			return errors.New("密码必须包含至少一个小写字母")
		}
		if !hasNumber {
			return errors.New("密码必须包含至少一个数字")
		}
		if !hasSpecial {
			return errors.New("密码必须包含至少一个特殊字符")
		}

		return nil
	}

	// 获取密码策略配置
	securityConfig := config.GlobalConfig.Security
	passwordConfig := securityConfig.Password

	// 检查最小长度
	if len(password) < passwordConfig.MinLength {
		return fmt.Errorf("密码长度至少需要%d位", passwordConfig.MinLength)
	}

	// 检查最大长度
	if len(password) > passwordConfig.MaxLength {
		return fmt.Errorf("密码长度不能超过%d位", passwordConfig.MaxLength)
	}

	var (
		hasUpper   = false
		hasLower   = false
		hasNumber  = false
		hasSpecial = false
	)

	// 检查每个字符
	for _, char := range password {
		switch {
		case unicode.IsUpper(char):
			hasUpper = true
		case unicode.IsLower(char):
			hasLower = true
		case unicode.IsNumber(char):
			hasNumber = true
		case unicode.IsPunct(char) || unicode.IsSymbol(char):
			hasSpecial = true
		}
	}

	// 检查是否需要大写字母
	if passwordConfig.RequireUpper && !hasUpper {
		return errors.New("密码必须包含至少一个大写字母")
	}

	// 检查是否需要小写字母
	if passwordConfig.RequireLower && !hasLower {
		return errors.New("密码必须包含至少一个小写字母")
	}

	// 检查是否需要数字
	if passwordConfig.RequireNumber && !hasNumber {
		return errors.New("密码必须包含至少一个数字")
	}

	// 检查是否需要特殊字符
	if passwordConfig.RequireSpecial && !hasSpecial {
		return errors.New("密码必须包含至少一个特殊字符")
	}

	return nil
}
